package com.zzt.spider.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zzt.spider.model.entity.VideoPlan;
import com.zzt.spider.model.mapper.VideoPlanMapper;
import com.zzt.spider.service.VideoPlanService;
import lombok.extern.slf4j.Slf4j;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.ParseException;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

@Service
@Slf4j
public class VideoPlanServiceImpl extends ServiceImpl<VideoPlanMapper, VideoPlan> implements VideoPlanService {

    private static final ObjectMapper MAPPER = new ObjectMapper();

    @Override
    public void updateChannel() {
        // 获取东八区当前时间 (UTC+8)
        Date now = new Date();
        List<VideoPlan> videoPlanList = this
                .list(
                        new LambdaQueryWrapper<VideoPlan>()
                                .eq(VideoPlan::getPushFlag, 0)
                                .eq(VideoPlan::getUploadFlag, 1)
                                .le(VideoPlan::getPushTime, now)
                );
        if (videoPlanList == null || videoPlanList.size() == 0){
            return;
        }
        for(VideoPlan plan : videoPlanList){
            JsonNode root = null;
            try {
                root = MAPPER.readTree(plan.getParam());
                JsonNode items = root.get("items");
                String comment = plan.getComment();
                // 1. 发媒体组
                sendMediaGroup(plan.getBotToken(), plan.getChannelId(), items, comment);

                // 2. 如果有 comment，就发一条 HTML 文本
//            if (comment != null && !comment.isBlank()) {
//                sendComment(plan.getBotToken(), plan.getChannelId(), comment);
//            }
                update(
                        new LambdaUpdateWrapper<VideoPlan>()
                                .eq(VideoPlan::getId, plan.getId())
                                .set(VideoPlan::getPushFlag, 1)
                );
            } catch (JsonProcessingException e) {
                throw new RuntimeException(e);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private static void sendMediaGroup(String botToken, String chatId, JsonNode items, String comment) throws IOException {
        StringBuilder mediaJson = new StringBuilder("[");
        MultipartEntityBuilder mb = MultipartEntityBuilder.create()
                .addTextBody("chat_id", chatId);

        Iterator<JsonNode> it = items.elements();
        int idx = 0;
        while (it.hasNext()) {
            JsonNode node = it.next();
            String type     = node.get("type").asText();  // photo or video
            String path     = node.get("path").asText();
            String attachId = "file" + (idx++);
            mediaJson.append("{")
                    .append("\"type\":\"").append(type).append("\",")
                    .append("\"media\":\"attach://").append(attachId).append("\"");
            if(!it.hasNext()){
                mediaJson.append(",")
                        .append("\"caption\":\"")
                        .append(escapeJson(comment))
                        .append("\",")
                        .append("\"parse_mode\":\"HTML\"");
            }
            if (node.has("thumb")) {
                String thumbPath = node.get("thumb").asText();
                String thumbId   = "thumb" + idx;

                mediaJson.append(",\"thumb\":\"attach://").append(thumbId).append("\"");

                // 把 thumb 文件加入 multipart
                File thumbFile = new File(thumbPath);
                if (!thumbFile.exists() || !thumbFile.canRead()) {
                    throw new IOException("Cannot access thumb file: " + thumbPath);
                }
                mb.addBinaryBody(thumbId, thumbFile, ContentType.DEFAULT_BINARY, thumbFile.getName());
            }
            mediaJson.append("}");
            if (it.hasNext()) mediaJson.append(",");

            Path filePath = Paths.get(path);
            log.info("Processing file at path: {}", filePath.toAbsolutePath());
            File f = filePath.toFile();

            if (!f.exists()) {
                log.error("File does not exist: {}", path);
                throw new IOException("File does not exist: " + path);
            }
            if (!f.canRead()) {
                log.error("Cannot read file: {}", path);
                throw new IOException("Cannot read file: " + path);
            }
            log.info("File {} exists and is readable.", path);

            mb.addBinaryBody(attachId, f, ContentType.DEFAULT_BINARY, f.getName());
        }
        mediaJson.append("]");

        mb.addTextBody("media", mediaJson.toString(), ContentType.APPLICATION_JSON);
        log.info(mediaJson.toString());
        String url = "https://api.telegram.org/bot" + botToken + "/sendMediaGroup";
        HttpPost post = new HttpPost(url);
        HttpEntity multipart = mb.build();
        post.setEntity(multipart);

        try (CloseableHttpClient client = HttpClients.createDefault();
             CloseableHttpResponse resp = client.execute(post)) {
            int status = resp.getCode();
            String body = EntityUtils.toString(resp.getEntity(), StandardCharsets.UTF_8);

            log.info("sendMediaGroup → status={} body={}", status, body);
            if (status != 200) {
                throw new IOException("sendMediaGroup failed: " + body);
            }
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    private static void sendComment(String botToken, String chatId, String html) throws IOException, InterruptedException {
        String url = "https://api.telegram.org/bot" + botToken + "/sendMessage";
        String form = "chat_id="   + URLEncoder.encode(chatId,   StandardCharsets.UTF_8)
                + "&text="      + URLEncoder.encode(html,     StandardCharsets.UTF_8)
                + "&parse_mode=HTML";

        HttpRequest req = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .header("Content-Type","application/x-www-form-urlencoded")
                .POST(HttpRequest.BodyPublishers.ofString(form))
                .build();

        HttpResponse<String> resp = HttpClient.newHttpClient()
                .send(req, HttpResponse.BodyHandlers.ofString());
        System.out.println("sendMessage → " + resp.statusCode() + " / " + resp.body());
    }

    private static String escapeJson(String s) {
        return s.replace("\\", "\\\\")
                .replace("\"", "\\\"")
                .replace("\n", "\\n")
                .replace("\r", "\\r");
    }

}
